
import 'package:flutter/material.dart';
import 'package:xsdk_flutter/xsdk/framework/bean/x_bean_grop.dart';
import 'package:xsdk_flutter/xsdk/framework/bean/x_bean_group_list_item.dart';
import 'package:xsdk_flutter/xsdk/framework/page/x_page_state.dart';
import 'package:xsdk_flutter/xsdk/utils/x_utils_log.dart';
import 'package:xsdk_flutter/xsdk/utils/x_utils_widget.dart';

/*
页面父类基础界面
listView通用State
支持分页

布局会暂满剩余空间
 */
abstract class XPageListViewState extends XPageState {

  final GlobalKey<AnimatedListState> _listStateKey = GlobalKey<AnimatedListState>();

  //AnimatedList动画时间
  final int _animatedListDurationMilliseconds=200;
  //是否支持滑动删除item(使用Dismissible)
  bool isEnableSlideRemoveItem=false;
  //分组listView,是否只有一个分组展开
  bool isGroupSingleExpanded=true;
  //GridList的列数
  int crossAxisCount=2;
  double gridChildAspectRatio=1.0;
  double? itemWidgetHeight;

  /*
  0:ListView(没有动画,支持滑动删除item);
  1:AnimatedList(支持手动点击添加/删除item动画,不支持拖拽item,不支持滑动删除item,常用场景:web);
  2:ReorderableListView(支持拖拽item);(重写onInterceptorIsListItemCanDrag和onInterceptorIsListItemCanMoveToTheListPosition)
  3:ExpansionPanelList分组listview(重写getGroupItemWidget())
  4.GridListview
   */
  int _listViewType=0;

  ScrollController? xScrollController;

  /*
  是否每个itemWidget使用GlobalKey,
  用于测量每个item所在的位置高度,滑动到指定item,
  注意:适用普通listview,不滑动删除
   */
  bool isItemWidgetUseGlobalKey=false;
  //final List<GlobalKey> _itemGlobalKeys = List.generate(100, (index) => GlobalKey());
  final List<GlobalKey> itemWidgetGlobalKeys = [];

  /*
  可在子类取消required(这里强制required则子类会提示生成构造方法)
  各种listview类型在子类的构造方法中设置其值
   */
  XPageListViewState(
      {
        super.isKeepPageState=false,
        super.xTag,
        super.handleAndFinishPageFunction,
        //是否支持拖拽item
        bool isEnableItemDrag=false,
        //是否支持滑动删除item
        this.isEnableSlideRemoveItem=false,
        //是否支持手动添加删除item动画(使用AnimatedList,不支持拖拽item,不支持滑动删除item,常用场景:web)
        bool isEnableManualAddOrRemoveItemAnimation=false,
        //是否分组(自带分组展开图标)
        bool isGroupList=false,
        //分组是否只有1个展开
        this.isGroupSingleExpanded=true,
        //是否网格GridList
        bool isGridList=false,
        //网格GridList的列数
        this.crossAxisCount=2,
        this.gridChildAspectRatio=1.0,//子view的宽高比,通过它跳转gridview每行高度(注意:gridview不会根据内容调节高度)
        this.itemWidgetHeight, //子view高度,为空则以childAspectRatio比例为准
        this.isItemWidgetUseGlobalKey=false,//是否每个itemWidget使用GlobalKey,适用普通listview
      }
      ){

    if(isGridList){
      //网格griview
      _listViewType=4;
    }else if(isGroupList){
      //分组
      _listViewType=3;
    }else if(getIsEnablePageLoadData()){
      //使用分页加载数据
      _listViewType=0;
    }else{
      //不分组
      if(isEnableItemDrag){
        //启用拖拽item(使用ReorderableListView),注意:每个itemWidget必须使用UniqueKey,否则报错
        _listViewType=2;
      }else if(isEnableSlideRemoveItem){
        //不启用拖拽item,但启用滑动删除item(使用ListView)
        _listViewType=0;
      }else if(isEnableManualAddOrRemoveItemAnimation){
        //支持手动添加删除item动画(使用AnimatedList,不支持拖拽item,不支持滑动删除item)
        _listViewType=1;
      }else{
        _listViewType=0;
      }
    }
    //
    XLogUtils.printLog('---_listViewType=$_listViewType');

  }


  //滑动到列表最后
  void scrollToEnd(){
    XWidgetUtils.scrollToListViewScrollViewEnd(
      scrollController: xScrollController,
      isAnimate:true,
      durationMilliseconds:_animatedListDurationMilliseconds,
    );
  }

  //是否临时滚动位置(中间过渡,轮动监听会响应,可从中判断)
  bool isTempScroll=false;

  //滑动到指定item,
  void scrollToItem(
      {
        int? itemIndex,//指定item下标
        double? offset,//指定滚动偏移量,
        bool isAnimate=true,
      }
      )
  {

    //init
    isTempScroll=false;

    //以itemIndex优先
    if(itemIndex!=null){

      if(itemIndex<=0){
        offset=0;
      }else{
        if(itemWidgetGlobalKeys.length!=0 && itemIndex<itemWidgetGlobalKeys.length){
          //适用item高度不固定

          //由于虚拟化的缘故，只有可见的 item 才会被渲染并且会有 currentContext，而那些不在视图内的 item 其 currentContext 会为 null
          BuildContext? targetContext = itemWidgetGlobalKeys[itemIndex].currentContext;

          if (targetContext != null) {

            //final RenderBox? renderBox = targetContext.findRenderObject() as RenderBox;
            //localToGlobal 方法将 item 的局部坐标转换为全局坐标，以便我们可以正确计算滚动的偏移量
            //offset = renderBox?.localToGlobal(Offset.zero).dy;

            //可通过Scrollable.ensureVisible滑动到指定item
            Scrollable.ensureVisible(targetContext,
                duration: isAnimate?Duration(milliseconds: _animatedListDurationMilliseconds):Duration.zero,
                curve: Curves.fastEaseInToSlowEaseOut);

          }else{
            XLogUtils.printLog('---targetContext=null,未能获得item高度,itemIndex=$itemIndex');
            //实测:未显示的item,RenderBox=null,不能通过RenderBox实现,也不能通过Scrollable.ensureVisible实现
            //
            int start=-1;
            int end=-1;
            BuildContext? targetContext_start;
            BuildContext? targetContext_end;

            for(int i=0;i<itemWidgetGlobalKeys.length;i++){
              if(start==-1 && itemWidgetGlobalKeys[i].currentContext!=null){
                start=i;
                targetContext_start=itemWidgetGlobalKeys[i].currentContext;
              }else if(start!=-1 && end==-1 && itemWidgetGlobalKeys[i].currentContext==null){
                end=i-1;
                targetContext_end=itemWidgetGlobalKeys[i-1].currentContext;
              }else if(start!=-1 && end==-1 && i==(itemWidgetGlobalKeys.length-1) && itemWidgetGlobalKeys[i].currentContext!=null){
                end=i;
                targetContext_end=itemWidgetGlobalKeys[i].currentContext;
              }else if(start!=-1 && end!=-1){
                break;
              }
            }

            XLogUtils.printLog('---start=$start,end=$end');
            if(itemIndex<start){
              targetContext=targetContext_start;
              XLogUtils.printLog('---先滑动到: $start');
            }else if(itemIndex>end){
              targetContext=targetContext_end;
              XLogUtils.printLog('---先滑动到: $end');
            }
            //注意:实测不能使用动画,否则会循环执行scrollToItem,实际无法滑动,因此要设置动画时间为0(内部为jumpTo)
            isTempScroll=true;
            Scrollable.ensureVisible(
                targetContext!,
                duration: Duration.zero
            );

            //
            WidgetsBinding.instance.addPostFrameCallback((Duration timeStamp) {
              XLogUtils.printLog('---再次调用scrollToItem');
              // for( int j=0; j<itemWidgetGlobalKeys.length;j++){
              //   GlobalKey gk = itemWidgetGlobalKeys[j];
              //   XLogUtils.printLog('---GlobalKey,index=$j; currentContext=${gk.currentContext!=null}');
              // }
              scrollToItem(itemIndex: itemIndex,isAnimate:isAnimate);
              return;
            });

          }

          //
          XLogUtils.printLog('---滑动到: $itemIndex');
          return;

        }else{
          //适用item高度固定
          offset=itemIndex * (itemWidgetHeight??50);
        }
      }

    }

    if(offset==null || offset<0){
      offset=0;
    }

    XLogUtils.printLog('---offset=$offset');

    if(isAnimate){
      xScrollController?.animateTo(
          offset,
          duration: Duration(milliseconds: _animatedListDurationMilliseconds),
          curve: Curves.fastEaseInToSlowEaseOut);
    }else{
      xScrollController?.jumpTo(offset);
    }

  }

  //重写方法///////////////////////////////////////////////////

  /*
  构建item的widget
  强转: Car item= listItem as Car;
  注意:
  1.getListItemWidget要以item绘制widget,避免使用position
  2.删除操作时,使用position(避免相同item情况)
  注意:有些listview要求每个item都需要有key,那么就要用XWidgetUtils.getLayoutContainer包一层
   */
  @required
  Widget getListItemWidget(dynamic listItem,int position);

  //
  Widget _getXListItemWidget(dynamic listItem,int position){

    if(_listViewType==2){
      //拖拽,每个itemWidget必须UniqueKey,否则报错;
      return XWidgetUtils.getLayoutContainer(
        key: UniqueKey(),
        child: getListItemWidget(listItem,position),
      );
    }else if(isItemWidgetUseGlobalKey
        && _listViewType==0
        && itemWidgetGlobalKeys.length!=0
    ){
      //不分页,普通listview,使用GlobalKey,可测量每个itemWidget所在的高度,用于滑动到指定item
      //XLogUtils.printLog('---普通listview,使用GlobalKey,可测量每个itemWidget所在的高度,用于滑动到指定item');
      return XWidgetUtils.getLayoutContainer(
        key: itemWidgetGlobalKeys[position],// 为每个 item 设置 GlobalKey
        child: getListItemWidget(listItem,position),
      );
    }

    return getListItemWidget(listItem,position);

  }

  /*
  构建分组头groupItem的widget
  强转: Car item= listItem as Car;
  注意:
  1.getListItemWidget要以item绘制widget,避免使用position
  2.删除操作时,可以使用position(避免相同item情况),使用removeUsePosition
   */
  Widget getGroupItemWidget(dynamic groupItem, bool isExpanded) {
    return XWidgetUtils.getWidgetText('重写getGroupItemWidget()');
  }

  //拖拽listview,需要重写的拦截方法/////////////////////////////////////////////////////////
  /*
  拦截器,判断某个item是否能被拖拽(适用:组头item不能被拖拽),
  默认值应该设置为true(都能被拖拽),已适配设置组头item不能被拖拽
   */
  bool onInterceptorIsListItemCanDrag(int index){
    return true;
  }

  /*
  拦截器,判断某个item是否能被拖拽到指定位置(业务实际)
  默认值应该设置为true(都能被拖拽到指定位置)
   */
  bool onInterceptorIsListItemCanMoveToTheListPosition(int itemFromListdataposition,int itemToListdataposition) {
    return true;
  }

  EdgeInsets getListViewPadding(){
    return XWidgetUtils.getEdgeInsets(0, 0, 0, 0);
  }

  //分页,重写/////////////////////////////////////////////////////////
  /*
  分页统一使用:
  widget.currentPageIndex;
  widget.totalPages;
   */

  //是否启用分页加载数据
  bool getIsEnablePageLoadData(){
    return false;
  }

  //是否启用下拉刷新数据
  bool getIsEnableRefreshLoadData(){
    return false;
  }

  @override
  bool getIsPageIndexStartWith1() {
    //分页加载是否从第1页开始,否则从0开始
    return true;
  }

  //滚动停止后的偏移量
  void onScrollStop(int itemIndex,double offset){}

  @override
  void onCreate() {
    super.onCreate();
    xScrollController = ScrollController(initialScrollOffset: widget.currentListViewPosition);
  }

  @override
  void onDestroy(){
    super.onDestroy();
    xScrollController?.dispose();
  }

  //私有方法/////////////////////////////////////////////////////////

  //背景圆角Widget(这个listview在一个圆角Widget中)
  bool getIsUseRoundedRectWidgetBackground(){
    return false;
  }

  /*
  添加AnimatedList控件
   */
  @override
  Widget getBodyWidget(BuildContext context) {

    if(widget.listData.length==0 && getEmptyDataWidget()!=null){
      return getEmptyDataWidget()!;
    }

    if(getIsUseRoundedRectWidgetBackground()){
      //实测:圆角layout会自动暂满剩余空间,注意:这里不能在Column嵌入listview和Spacer(除非固定listview高度)
      return XWidgetUtils.getXLayoutRoundedRect(
          margin: XWidgetUtils.getEdgeInsets(10, 10, 10, 10),
          child:_createListView()
      );
    }else{
      return _createListView();
    }

  }

  //当没有数据时,显示提示图
  Widget? getEmptyDataWidget(){
    return null;
  }


  Widget _createListView(){

    if(_listViewType==1){
      //使用有动画效果的 AnimatedList
      return XWidgetUtils.getWidgetAnimatedList(
        key:_listStateKey,
        padding:getListViewPadding(),
        listData:widget.listData,
        scrollController:xScrollController,
        listItemWidgetFunction: (BuildContext context, int index, Animation<double> animation){
          //支持item左右上下滑动
          return _buildAnimatedListItemWidget(widget.listData[index],index,animation,true);
        },
      );
    }else if(_listViewType==2){
      //支持拖拽item的ReorderableListView
      return XWidgetUtils.getWidgetReorderableListView(
        listData:widget.listData,
        padding:getListViewPadding(),
        scrollController:xScrollController,
        listItemWidgetFunction: (BuildContext context, int index){
          //支持item左右上下滑动
          return isEnableSlideRemoveItem?_buildDismissibleForSupportItemSlideRemove(widget.listData[index],index):_getXListItemWidget(widget.listData[index],index);
        },
        onReorder:  (int oldIndex, int newIndex){
          //拖拽位置变动
          if(oldIndex!=newIndex){

            //判断item是否能被拖拽到指定位置(业务)
            if(!onInterceptorIsListItemCanMoveToTheListPosition(oldIndex,newIndex)){
              return;
            }

            setState(() {
              if(newIndex>oldIndex) {
                newIndex -= 1;
              }
              dynamic tempItem = widget.listData.removeAt(oldIndex);
              widget.listData.insert(newIndex, tempItem);
            });
          }

        },
        //拦截器,判断某个item是否能被拖拽(适用:组头item不能被拖拽)
        onInterceptorIsListItemCanDrag: (int index) {

          //判断组头item不能被拖拽
          if(widget.listData[index] is XBeanGroupItem){
            XBeanGroupItem iitem = widget.listData[index] as XBeanGroupItem;
            if(iitem.isGroupItem){
              XLogUtils.printLog('---判断组头item不能被拖拽');
              return false;
            }
          }

          return onInterceptorIsListItemCanDrag(index);
        },
      );
    }else if(_listViewType==3){

      if(isGroupSingleExpanded){
        //只有1个分组展开
        return XWidgetUtils.getWidgetExpansionPanelRadioList(
          listData: widget.listData,
          padding:getListViewPadding(),
          scrollController:xScrollController,
          groupItemWidgetFunction: (dynamic groupItem, bool? isExpanded){
            return getGroupItemWidget(groupItem,isExpanded!);
          },
          listItemWidgetFunction: (dynamic listItem,int index){
            return _getXListItemWidget(listItem,index);
          },
        );

      }else{
        //多个分组可展开
        return XWidgetUtils.getWidgetExpansionPanelList(
            listData: widget.listData,
            padding:getListViewPadding(),
            scrollController:xScrollController,
            groupItemWidgetFunction: (dynamic groupItem, bool? isExpanded){
              return getGroupItemWidget(groupItem,isExpanded!);
            },
            listItemWidgetFunction: (dynamic listItem,int index){
              return _getXListItemWidget(listItem,index);
            },
            expansionCallback: (int panelIndex, bool isExpanded){
              setState(() {
                XBeanExpansionItem item= widget.listData[panelIndex] as XBeanExpansionItem;
                item.isExpanded = !isExpanded;
              });
            });
      }

    }else if(_listViewType==4){
      //网格Listview
      return XWidgetUtils.getWidgetGridView(
          crossAxisCount: crossAxisCount,
          childAspectRatio:gridChildAspectRatio,
          childHeight:itemWidgetHeight,
          listData: widget.listData,
          padding:getListViewPadding(),
          listItemWidgetFunction: (BuildContext context,int index){
            return _getXListItemWidget(widget.listData[index],index);
          },
          initialScrollOffset: widget.currentListViewPosition,
          scrollController:xScrollController,
          onNotifyScrollStop: (ScrollController? scrollController){
            widget.currentListViewPosition=scrollController?.offset??0.0;
          },
          onNotifyScrollBottomPosition: !getIsEnablePageLoadData()?null:(e){
            //滑动到底部通知,加载下一页
            if(widget.currentPageIndex<widget.totalPages){
              updateData(pageIndex: widget.currentPageIndex+1);
            }
          },
          onRefresh: !getIsEnableRefreshLoadData()?null:() async{
            widget.currentListViewPosition=0.0;
            updateData(pageIndex: getIsPageIndexStartWith1()?1:0);
          }
      );
    }else{
      //使用普通的ListView(支持滑动删除item)
      return XWidgetUtils.getWidgetListView(
          listData:widget.listData,
          padding:getListViewPadding(),
          itemExtent: itemWidgetHeight,
          listItemWidgetFunction:(BuildContext context,int index){
            //支持item左右上下滑动
            return isEnableSlideRemoveItem?_buildDismissibleForSupportItemSlideRemove(widget.listData[index],index):_getXListItemWidget(widget.listData[index],index);
          },
          initialScrollOffset: widget.currentListViewPosition,
          scrollController:xScrollController,
          onNotifyScrollStop: (ScrollController? scrollController){
            widget.currentListViewPosition=scrollController?.offset??0.0;

            //计算当前属于第几个item
            if(isItemWidgetUseGlobalKey
                && _listViewType==0
            ){

              //
              for(int k=0;k<itemWidgetGlobalKeys.length;k++){
                final RenderBox? renderBox = itemWidgetGlobalKeys[k].currentContext?.findRenderObject() as RenderBox?;
                if(renderBox!=null){
                  //localToGlobal 方法将 item 的局部坐标转换为全局坐标，以便我们可以正确计算滚动的偏移量
                  double itemOffset = renderBox.localToGlobal(Offset.zero).dy;
                  double itemHeight = renderBox.size.height; // 获取实际高度
                  XLogUtils.printLog('---当前renderBoxs,k=$k, itemOffset=$itemOffset, itemHeight=$itemHeight, currentListViewPosition=${widget.currentListViewPosition}');
                }
              }

              //
              int itemIndex=-1;
              for(int j=0;j<itemWidgetGlobalKeys.length;j++){
                final RenderBox? renderBox = itemWidgetGlobalKeys[j].currentContext?.findRenderObject() as RenderBox?;
                if(renderBox!=null){
                  //localToGlobal 方法将 item 的局部坐标转换为全局坐标，以便我们可以正确计算滚动的偏移量
                  double itemOffset = renderBox.localToGlobal(Offset.zero).dy;
                  double itemHeight = renderBox.size.height; // 获取实际高度

                  if(itemOffset>0){
                    if(itemOffset>itemHeight){
                      itemIndex=j-1;
                    }else{
                      itemIndex=j;
                    }
                    break;
                  }

                }

              }

              if(itemIndex<0){
                itemIndex=0;
              }

              XLogUtils.printLog('---onScrollStop,itemIndex=$itemIndex,offset=${widget.currentListViewPosition}');
              onScrollStop(itemIndex, widget.currentListViewPosition);
            }else{
              XLogUtils.printLog('---onScrollStop,itemIndex=不计算,固定0,offset=${widget.currentListViewPosition}');
              onScrollStop(0,widget.currentListViewPosition);
            }

          },
          onNotifyScrollBottomPosition: !getIsEnablePageLoadData()?null:(e){
            //滑动到底部通知,加载下一页
            if(widget.currentPageIndex<widget.totalPages){
              updateData(pageIndex: widget.currentPageIndex+1);
            }
          },
          onRefresh: !getIsEnableRefreshLoadData()?null:() async{
            widget.currentListViewPosition=0.0;
            updateData(pageIndex: getIsPageIndexStartWith1()?1:0);
          }
      );
    }
  }



  //(私有方法)创建listItem的Widget,支持动画
  /*
    使用position(删除item后导致listData下标变化),注意:删除动作执行此方法,动画效果时,
    问题1: 实测删除最后1个item时会报错的情况:
    原因在此方法外执行listData删除item动作,因为动画线程异步,实际listData已经删除item(已经不存在任何item),则不能再让其执行下面的getListItemWidget绘制widget了,
    解决办法: 返回一个没有position关联的widget;
    问题2:在此方法外执行listData删除item动作,因为动画线程异步,实际listData已经删除item,删除动画中的item并不是对应删除item,而是它的下一个item的widget动画,
    如果改为:不在此方法外删除listData中的item,而在此方法中添加监听动画状态,当动画消失时,再删除对应listData中的item,则可以保证删除动画对应的是删除的那个item,
    但存在的问题更严重,界面显示没有删除的下1个item先变成要删除的那个item,然后再变回正常没有删除的item,原因是同时绘制界面造成的;
    因此最好的解决办法:getListItemWidget不使用position,而直接使用item绘制widget,则不会存在上面的问题
     */
  // Widget _buildAnimatedListItemWidget(
  //     int position,
  //     Animation<double> animation,
  //     bool isAddItem//是否添加item,否则为删除item
  //     ){
  //   if(listData.length==0){
  //     return XWidgetUtils.getLayoutContainer();
  //   }
  //   // if(!isAddItem){
  //   //   animation.addStatusListener((status) {
  //   //     if(status==AnimationStatus.dismissed){
  //   //       XLogUtils.printLog('----删除item:$status');
  //   //       listData.removeAt(position);
  //   //     }
  //   //   });
  //   // }
  //
  //   //渐变
  //   return FadeTransition(
  //     opacity: animation.drive(CurveTween(curve:isAddItem? Curves.easeIn:Curves.easeOut)),
  //     //位置移动(右入右出)
  //     child: SlideTransition(
  //       //easeInCirc,easeInExpo,bounceOut fastLinearToSlowEaseIn 速度节奏等不一样
  //       position: animation.drive(CurveTween(curve:isAddItem? Curves.fastLinearToSlowEaseIn:Curves.easeOutExpo))
  //           .drive(Tween<Offset>(begin: const Offset(1,0),end: const Offset(0,0))),
  //       child: getListItemWidget(position),
  //     ),
  //   );
  // }
  //getListItemWidget以item绘制widget,避免使用position
  Widget _buildAnimatedListItemWidget(
      dynamic listItem,
      int position,
      Animation<double> animation,
      bool isAddItem//是否添加item,否则为删除item
      ){

    //渐变
    return FadeTransition(
      opacity: animation.drive(CurveTween(curve:isAddItem? Curves.easeInExpo:Curves.easeOutExpo)),
      //位置移动(右入右出)
      child: SlideTransition(
        //easeInCirc,easeInExpo,bounceOut fastLinearToSlowEaseIn 速度节奏等不一样
        position: animation.drive(CurveTween(curve:isAddItem? Curves.easeInExpo:Curves.easeOutExpo))
            .drive(Tween<Offset>(begin: const Offset(1,0),end: const Offset(0,0))),
        //支持item滑动删除
        child: _getXListItemWidget(listItem,position),
      ),
    );
  }


  /*
  使用Dismissible支持item滑动:

  direction 为限制滑动关闭方向，在 onDismissed / confirmDismiss 中也可以进行判断；
DismissDirection.vertical 竖直方向，包括 up / down 两种
DismissDirection.horizontal 水平方向，包括 endToStart / startToEnd 两种
DismissDirection.endToStart 结束到开始方向(与语言设置的 rtl 和 ltr 相关)，汉英等日常方向一般是从右至左
DismissDirection.startToEnd 开始到结束方向(与语言设置的 rtl 和 ltr 相关)，汉英等日常方向一般是从左至右
DismissDirection.up 由下向上
DismissDirection.down 由上向下

confirmDismiss 返回的是 Future 类型的数据，用于判断是否可清除当前 Widget，
返回 true 时清除此 Widget，否则将其移回到其原始位置；
当返回 false / null 时，均不会进入 onDismissed / onResize 回调；
其中 onDismissed 为确认清除当前 Widget 的回调，onResize 为当前 Widget 改变尺寸时的回调；
在 confirmDismiss / onDismissed 中可以根据 direction 滑动方向进行单独判断；

  dismissThresholds 可根据各方向设置不同的阀值，对应的是一个 Map 集合；范围在(0.0, 1.0) 之间，设置的阀值越大，代表滑动范围越大才可以触发 onDismissed 回调；
  dismissThresholds: {
  DismissDirection.startToEnd: 0.8,
  DismissDirection.endToStart: 0.3
},
   */

  Widget _buildDismissibleForSupportItemSlideRemove(dynamic listItem,int position){
    return Dismissible(
      key:UniqueKey(),
      //onUpdate: ,//每个滑动像素事件
      //confirmDismiss: ,//默认item全都可删除
      //onResize:,//重新修改尺寸回调(优先onDismissed执行)
      onDismissed: (DismissDirection direction){
        //滑动有效触发后回调(ui移除item)
        //XLogUtils.printLog('----item滑动方向= $direction,position=$position');
        //删除数据ok(注意:实测Dismissible的删除并没有更新ui的位置,即position没有更新,因此不能用removeAt(),Dismissible只能和ListView一起使用,不能和AnimatedList使用(无法更新AnimatedList的ui中的item位置))
        setState(() {
          widget.listData.remove(listItem);
        });
      },
      //滑动方向(向左向右滑动都可删除)
      direction: DismissDirection.horizontal,//!isItemSupportSlideRemove?DismissDirection.none:DismissDirection.horizontal,
      background: _createDismissibleRemoveBackgroundWidget(),
      secondaryBackground: _createSecondDismissibleRemoveBackgroundWidget(),
      child: getListItemWidget(listItem,position),//这里不嵌套_getXListItemWidget,因为Dismissible已使用UniqueKey
    );

  }

  //滑出item删除时(向左滑),Dismissible的背景widget,显示删除图标
  _createDismissibleRemoveBackgroundWidget() {
    return XWidgetUtils.getLayoutContainer(
        backgroundColor: const Color(0xffff0000),
        child: XWidgetUtils.getLayoutAlign(
          alignment:Alignment.centerLeft,
          child:XWidgetUtils.getLayoutPadding(
              padding:const EdgeInsets.symmetric(horizontal: 15.0),
              child:XWidgetUtils.getLayoutFittedBox(
                  XWidgetUtils.getLayoutColumn(
                      children:[
                        const Icon(Icons.delete, color: Colors.white),
                        const Text('删除', style: TextStyle(color: Colors.white,fontSize: 12))
                      ]))
          ),
        )
    );
  }

  //Dismissible的第二背景(向右滑)
  _createSecondDismissibleRemoveBackgroundWidget() {
    return XWidgetUtils.getLayoutContainer(
        backgroundColor: const Color(0xffff0000),
        child: XWidgetUtils.getLayoutAlign(
          alignment:Alignment.centerRight,
          child:XWidgetUtils.getLayoutPadding(
              padding:const EdgeInsets.symmetric(horizontal: 15.0),
              child:XWidgetUtils.getLayoutFittedBox(
                  XWidgetUtils.getLayoutColumn(
                      children:[
                        const Icon(Icons.delete, color: Colors.white),
                        const Text('删除', style: TextStyle(color: Colors.white,fontSize: 12))
                      ]))
          ),
        )
    );
  }



  //增删item公开方法 分页///////////////////////////////////////////////////////////////
  void setXListData_pageIndexData(int? pageIndex, int? pageCount, List<dynamic>? items){
    if(mounted){
      setState((){

        pageIndex??=0;
        pageCount??=0;

        //判断是否删除所有数据
        if(getIsPageIndexStartWith1()){
          //分页从第1页开始
          if(pageIndex==0 || pageIndex==1){
            widget.listData.clear();
            itemWidgetGlobalKeys.clear();
          }
        }else{
          //分页从0开始
          if(pageIndex==0){
            widget.listData.clear();
            itemWidgetGlobalKeys.clear();
          }
        }

        widget.currentPageIndex=pageIndex!;
        widget.totalPages=pageCount!;

        //
        if(items!=null){
          widget.listData.addAll(items);

          if(isItemWidgetUseGlobalKey
              && _listViewType==0
          ){
            itemWidgetGlobalKeys.addAll(List.generate(items.length, (index) => GlobalKey()));
          }

        }

      });
    }

  }


  //增删item公开方法 不分页///////////////////////////////////////////////////////////////

  //追加单条数据,适合ListView,AnimatedList使用;但不适合Dismissible,itemWidgetGoldKeys,),/////////////////////////////////////////////////////////
  void setXListData_addOneItem(
      dynamic item,
      {
        int? position, //插入位置
      }
      ){

    if(mounted){
      //先添加item,后更新
      if(position==null || position<0){
        //在末尾添加
        position=widget.listData.length;
        widget.listData.add(item);
      }else{
        //按位置插入
        if(position>widget.listData.length){
          position=widget.listData.length;
        }
        widget.listData.insert(position, item);
      }

      /*
    更新
    ListView,使用setState
    AnimatedList实测使用setState更新无效,和使用_listStateKey.currentState!.setState();也是无效的)
     */
      if(_listViewType==1){
        //AnimatedList, _listStateKey?.currentState等同于AnimatedList.maybeOf(BuildContext context)
        _listStateKey.currentState?.insertItem(position,duration:  Duration(milliseconds: _animatedListDurationMilliseconds));
      }else{
        //ListView
        setState((){
          if(isItemWidgetUseGlobalKey
              && _listViewType==0
          ){
            //init
            itemWidgetGlobalKeys.clear();
            itemWidgetGlobalKeys.addAll(List.generate(widget.listData.length, (index) => GlobalKey()));
          }
        });
      }
    }

  }

  //追加多条
  void setXListData_addAllItems(
      List<dynamic>? items,
      {
        int? position, //插入位置
        bool isReplaceAllItems=true,//替换所有数据
      }
      ){

    if(mounted){
      //
      if(isReplaceAllItems){
        //删除所有数据
        if(_listViewType==1){
          //AnimatedList, 先更新,后删除, AnimatedList不能使用listData.clear();后数量不对报错!
          while(widget.listData.isNotEmpty){
            // _listStateKey?.currentState等同于AnimatedList.maybeOf(BuildContext context)
            //从第1个开始删除
            dynamic removeItem= widget.listData.removeAt(0);
            //
            _listStateKey.currentState?.removeItem(
                0,
                duration: Duration(milliseconds: _animatedListDurationMilliseconds),
                    (context, animation){
                  //
                  return _buildAnimatedListItemWidget(removeItem,0, animation,false);
                });
          }

        }else{
          //ListView
          widget.listData.clear();
        }
      }

      if(items!=null){
        //先添加item,后更新
        if(position==null || position<0){
          //在末尾添加
          position=widget.listData.length;
          widget.listData.addAll(items);
        }else{
          //按位置插入
          widget.listData.insertAll(position, items);
        }
      }

      /*
    更新
    ListView,使用setState
    AnimatedList实测使用setState更新无效,和使用_listStateKey.currentState!.setState();也是无效的)
     */
      if(_listViewType==1 && items!=null){
        //AnimatedList, _listStateKey?.currentState等同于AnimatedList.maybeOf(BuildContext context)
        for (int offset = 0; offset < items.length; offset++) {
          _listStateKey.currentState?.insertItem(position??widget.listData.length + offset,duration:  Duration(milliseconds: _animatedListDurationMilliseconds));
        }
      }else{
        //ListView
        setState((){
          if(isItemWidgetUseGlobalKey
              && _listViewType==0
          ){
            //init
            itemWidgetGlobalKeys.clear();
            itemWidgetGlobalKeys.addAll(List.generate(widget.listData.length, (index) => GlobalKey()));
          }
        });
      }
    }

  }

  //删除数据(适合存在重复相同的数据,按位置删除)
  void setXListData_removeItemByPosition(int position){
    if(mounted){
      if(_listViewType==1){
        //删除
        dynamic removeItem=widget.listData.removeAt(position);

        //AnimatedList, _listStateKey?.currentState等同于AnimatedList.maybeOf(BuildContext context)
        _listStateKey.currentState?.removeItem(
            position,
            duration: Duration(milliseconds: _animatedListDurationMilliseconds),
                (context, animation){
              //测试不能在这里删除或获得item,点击过快会报错!
              //dynamic removeItem= listData.removeAt(position);
              //dynamic removeItem= listData[position];
              //
              return _buildAnimatedListItemWidget(removeItem,position, animation,false);
            });

      }else{
        //ListView,先删除后更新

        setState((){
          widget.listData.removeAt(position);

          if(isItemWidgetUseGlobalKey
              && _listViewType==0
          ){
            //init
            itemWidgetGlobalKeys.clear();
            itemWidgetGlobalKeys.addAll(List.generate(widget.listData.length, (index) => GlobalKey()));
          }

        });
      }

    }

  }

  //删除数据(注意:不适合存在重复相同的数据情景)
  // void removeItem(dynamic item){
  //   if(isUseAnimatedList){
  //     //删除
  //     int position=listData.indexOf(item);
  //     dynamic removeItem=listData.removeAt(position);
  //
  //     //AnimatedList, _listStateKey?.currentState等同于AnimatedList.maybeOf(BuildContext context)
  //     _listStateKey.currentState?.removeItem(
  //         position,
  //         duration: Duration(milliseconds: _animatedListDurationMilliseconds),
  //             (context, animation){
  //           //测试不能在这里删除或获得item,点击过快会报错!
  //           //dynamic removeItem= listData.removeAt(position);
  //           //dynamic removeItem= listData[position];
  //           //
  //           return _buildListItemWidget(removeItem,position, animation,false);
  //         });
  //
  //   }else{
  //     //ListView,先删除后更新
  //     listData.remove(item);
  //     setState((){});
  //   }
  // }

  //删除所有数据
  void setXListData_removeAllItems(){

    if(mounted){
      if(_listViewType==1){
        //AnimatedList, 先更新,后删除, AnimatedList不能使用listData.clear();后数量不对报错!
        while(widget.listData.isNotEmpty){
          // _listStateKey?.currentState等同于AnimatedList.maybeOf(BuildContext context)
          //从第1个开始删除
          dynamic removeItem= widget.listData.removeAt(0);
          //
          _listStateKey.currentState?.removeItem(
              0,
              duration: Duration(milliseconds: _animatedListDurationMilliseconds),
                  (context, animation){
                //
                return _buildAnimatedListItemWidget(removeItem,0, animation,false);
              });
        }

      }else{
        //ListView

        setState((){
          //删除所有数据
          widget.listData.clear();
          itemWidgetGlobalKeys.clear();
        });

      }

    }

  }



}